﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
using System.Net;
using System.Linq;
using OPCAutomation;
using hegang_winform.domain;

namespace hegang_winform.services
{
    public class KEPWareDataAdapter
    {
        #region 成员变量
        OPCServer KEPServer = null;
        OPCGroups OpcGroups;
        public OPCGroup[] MyGroups;
        OPCItems [] MyItems;
        OPCItem[] MyItem;
        List<string> opcItemsArray;
        List<string> opcDeviceArray;
        OPCBrowser opcBrowser = null;
        PLCDataPack[] pack;
        int itmHandleClient = 0;
        OPCItem opcItem;
        public Hashtable htOpcItems = new Hashtable();
        private bool _ConnectionState = false;
        #endregion
        /// <summary>
        /// 初始化连接
        /// </summary>
        public KEPWareDataAdapter()
        {
            try
            {
                if (KEPServer == null)
                {
                    this.KEPServer = new OPCServer();
                }
            }catch(Exception e)
            {
                throw new Exception("KEPWareDataAdapter初始化失败。");
            }
        }

        public void Close()
        {
            //释放所有组资源
            KEPServer.OPCGroups.RemoveAll();
            //断开服务器
            KEPServer.Disconnect();
        }

        /// <summary>
        /// 创建数据组
        /// </summary>
        /// <returns></returns>
        public bool CreateGroup(List<string> device)
        {

            if (this.opcBrowser == null)
                throw new Exception("服务器没有连接……");
            if (this.opcDeviceArray == null)
                throw new Exception("没有找到需要监测的PLC设备……");
            if (device.Count == 0)
                throw new Exception("请先选择需要监测的PLC设备……");
            if (this.opcItemsArray == null)
            {
                opcItemsArray = new List<string>();
            }
            try
            {
                //设置组属性                                        
                KEPServer.OPCGroups.DefaultGroupIsActive = true;//激活组。
                KEPServer.OPCGroups.DefaultGroupDeadband = 0;// 死区值，设为0时，服务器端该组内任何数据变化都通知组。
                KEPServer.OPCGroups.DefaultGroupUpdateRate = 200;//默认组群的刷新频率为200ms

                OpcGroups = KEPServer.OPCGroups;
                MyGroups = new OPCGroup[device.Count];
                MyItems = new OPCItems[device.Count];
                pack = new PLCDataPack[device.Count];
                for (int i = 0; i < device.Count; i++)
                {
                    MyGroups[i] = OpcGroups.Add(device[i]);//测试删除组
                    MyGroups[i].UpdateRate = 100;//刷新频率为0.1秒。
                    MyGroups[i].IsActive = true;
                    MyGroups[i].IsSubscribed = true;//使用订阅功能，即可以异步，默认false

                    //MyGroups[i].AsyncRead();
                    //副井.副提升电控.提人方式

                    MyItems[i] = MyGroups[i].OPCItems;

                    foreach (var item in opcBrowser)
                    {
                        if (item.ToString().IndexOf(device[i]) >= 0)
                        {
                            opcItemsArray.Add(item.ToString());
                            htOpcItems.Add(itmHandleClient++, item);
                            //Console.WriteLine("ITEM:" + item.ToString() + "  " + itmHandleClient);
                            opcItem = MyItems[i].AddItem(item.ToString(), itmHandleClient);
                        }
                    }
                }
            }
            catch (Exception err)
            {
                string errMsg = string.Format("创建组出现错误：{0}", err.Message);
                throw new Exception(errMsg);
            }
            return true;
        }
        

        #region 打开和关闭连接
        /// <summary>
        /// 枚举本地OPC服务器
        /// </summary>
        public object GetLocalServer()
        {
            try
            {
                if(KEPServer == null)
                    KEPServer = new OPCServer();
                object serverList = KEPServer.GetOPCServers(Environment.MachineName);
                return serverList;
            }
            catch (Exception err)
            {
                string errMsg = string.Format("枚举本地OPC服务器出错：{0}", err.Message);
                throw new Exception(errMsg);
            }
        }

        /// <summary>
        /// 枚举本地OPC服务器
        /// </summary>
        public Dictionary<string,List<string>> GetPLCDevices()
        {
            Dictionary<string, List<string>> devices = new Dictionary<string, List<string>>();
            if (KEPServer == null)
                throw new Exception("OPC服务器没有连接");
            try
            {
                opcBrowser = KEPServer.CreateBrowser();
                opcBrowser.ShowBranches();
                opcBrowser.ShowLeafs(true);
                int count = opcBrowser.Count;
                int nPoint1 = -1, nPoint2 = -1;

                if (this.opcDeviceArray == null)
                {
                    opcDeviceArray = new List<string>();
                }

                foreach (var item in opcBrowser)
                {
                    if (item.ToString().IndexOf(".") == -1 || item.ToString().IndexOf("_") != -1)
                        continue;
                    nPoint1 = item.ToString().IndexOf(".");
                    nPoint2 = item.ToString().IndexOf(".", nPoint1 + 1);

                    if (!opcDeviceArray.Contains(item.ToString().Substring(0, nPoint2)))
                        opcDeviceArray.Add(item.ToString().Substring(0, nPoint2));

                    string key = item.ToString().Substring(0, nPoint1);
                    string value = item.ToString().Substring(nPoint1 + 1, nPoint2-nPoint1-1);
                    if (!devices.ContainsKey(key))
                    {
                        List<string> values = new List<string>();
                        values.Add(value);
                        devices.Add(key, values);
                    }
                    else
                    {
                        if(!devices[key].Contains(value))
                            devices[key].Add(value);
                    }
                }
            }
            catch (Exception err)
            {
                string errMsg = string.Format("获取PLC设备连接出错：{0}", err.Message);
                throw new Exception(errMsg);
            }
            return devices;
        }

        /// <summary>
        /// 创建服务器（远程模式）
        /// </summary>
        /// <param name="RemoteAddr">要连接远程服务器IP</param>
        /// <returns>执行连接是否成功</returns>
        public Result ConnectRemoteServer(string remoteHostName)
        {
            Result result = new Result();
            string msg = "";
            bool flag;
            if (_ConnectionState)
            {
                msg = string.Format("已连接到：{0}", KEPServer.ServerName);
                flag = true;
                return result;
            }
            try
            {
                KEPServer.Connect(remoteHostName);//连接本地服务器：服务器名+主机名或IP, remoteAddr
                if (KEPServer.ServerState == (int)OPCServerState.OPCRunning)
                {
                    msg = string.Format("已连接到：{0}", KEPServer.ServerName);
                    flag = true;
                }
                else
                {
                    msg = string.Format("{0}状态：{1}", KEPServer.ServerName, KEPServer.ServerState);
                    flag = false;
                }
                KEPServer.ServerShutDown += ServerShutDown;//服务器断开事件
            }
            catch (Exception err)
            {
                string errMsg = string.Format("连接远程服务器出现错误：{0}", err.ToString());
                throw new Exception(errMsg);
            }
            result.Flag = flag;
            result.Msg = msg;
            return result;
        }

        /// <summary>
        /// 断开与服务器的连接
        /// </summary>
        /// <param name="Reason"></param>
        public void ServerShutDown(string Reason)//服务器先行断开
        {
            if (KEPServer == null)
                return;
            if(KEPServer.OPCGroups.Count > 0)
                KEPServer.OPCGroups.RemoveAll();
            if(KEPServer.ServerState == 1)
            KEPServer.Disconnect();
            Trace.WriteLine("服务器已经先行断开！");
        }
        #endregion

        public void readData(int transactionid)
        {
            for(int i = 0; i < MyGroups.Length; i++)
            {
                OPCItems items = MyGroups[i].OPCItems;

                int numItems = items.Count;
                Console.WriteLine("numItems:" + numItems);

                int[] temp = new int[numItems + 1];
                temp[0] = 0;
                int j = 1;

                foreach (OPCItem item in items)
                {
                    temp[j] = item.ServerHandle;
                    j++;
                }

                Console.WriteLine("read begin");

                Array serverHandles = (Array)temp;
                Array Errors;
                int cancelID;

                MyGroups[i].AsyncRead(numItems, ref serverHandles, out Errors, transactionid, out cancelID);
            }

            /*OPCItems items = group.OPCItems;
            int numItems = items.Count;

            Console.WriteLine("numItems:" + numItems);

            int[] temp = new int[numItems + 1];
            temp[0] = 0;
            int i = 1;

            foreach (OPCItem item in items)
            {
                temp[i] = item.ServerHandle;
                i++;
            }

            Console.WriteLine("read begin");

            Array serverHandles = (Array)temp;
            Array Errors;
            int cancelID;

            group.AsyncRead(numItems, ref serverHandles, out Errors, transactionid, out cancelID);*/
        }
    }
}
